package com.heima.search.service.impl;

import com.alibaba.fastjson.JSON;
import com.heima.model.behavior.pojos.ApBehaviorEntry;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.search.dtos.UserSearchDto;
import com.heima.model.user.pojos.ApUser;
import com.heima.search.feign.BehaviorFeign;
import com.heima.search.service.ApUserSearchService;
import com.heima.search.service.ArticleSearchService;
import com.heima.search.utils.threadlocal.AppThreadLocalUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
@Service
@Slf4j
public class ArticleSearchServiceImpl implements ArticleSearchService {
    @Autowired
    private RestHighLevelClient client;
    @Autowired
    private BehaviorFeign behaviorFeign;

    @Autowired
    private ApUserSearchService apUserSearchService;

    private static final String INDEXNAME="app_info_article";
    @Override
    public ResponseResult search(UserSearchDto dto) throws IOException {
        //检查参数
        if(dto==null||dto.getSearchWords()==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        if (dto.getMinBehotTime()==null){
            dto.setMinBehotTime(new Date());
        }
        if(dto.getFromIndex() == 0){
            ApBehaviorEntry entry = getEntry(dto);
            if(entry != null){
                apUserSearchService.insert(entry.getId(),dto.getSearchWords());
            }else {
                log.error("记录搜索历史失败，未获取到行为实体数据");
            }
        }
        SearchSourceBuilder builder = new SearchSourceBuilder();
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();

        QueryStringQueryBuilder stringQueryBuilder = QueryBuilders.queryStringQuery(dto.getSearchWords()).field("title").field("content").defaultOperator(Operator.OR);

        boolQuery.must(stringQueryBuilder);

        RangeQueryBuilder publishTime = QueryBuilders.rangeQuery("publishTime").lt(dto.getMinBehotTime());
        boolQuery.must(publishTime);

        builder.query(boolQuery).from(0).size(dto.getPageSize()).highlighter(new HighlightBuilder().field("title").preTags("<span style='color:red'>").postTags("<span>")).sort("publishTime", SortOrder.DESC);
        SearchRequest request = new SearchRequest(INDEXNAME);
        request.source(builder);
        SearchResponse search = client.search(request, RequestOptions.DEFAULT);


        SearchHit[] hits = search.getHits().getHits();
        List<Map> maps = new ArrayList<>();
        for (SearchHit hit : hits) {
            String sourceAsString = hit.getSourceAsString();
            Map map = JSON.parseObject(sourceAsString, Map.class);

            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            HighlightField title = highlightFields.get("title");
            Text[] fragments = title.getFragments();

            String join = StringUtils.join(fragments);

            map.put("title",join);
            maps.add(map);
        }


        return ResponseResult.okResult(maps);
    }

    @Override
    public void saveArticle(String articleId, Map article) throws IOException {
        IndexRequest request = new IndexRequest(INDEXNAME);
        request.source(JSON.toJSONString(article), XContentType.JSON);
        client.index(request,RequestOptions.DEFAULT);
    }
    @Override
    public void deleteArticle(String articleId) throws IOException {
        DeleteRequest request = new DeleteRequest(INDEXNAME,articleId);
        client.delete(request,RequestOptions.DEFAULT);
    }
    private ApBehaviorEntry getEntry(UserSearchDto userSearchDto) {
        ApUser user = AppThreadLocalUtils.getUser();
        return behaviorFeign.findByUserIdOrEntryId(user==null? 0 : user.getId() , userSearchDto.getEquipmentId());
    }
}
